package br.com.pucrs.tcc.bd;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;

import br.com.pucrs.tcc.ed.AreaInteresse;
import br.com.pucrs.tcc.ed.GrupoTrabalho;
import br.com.pucrs.tcc.ed.Professor;
import br.com.pucrs.tcc.ed.ProfessorPretendido;
import br.com.pucrs.tcc.enumerator.SituacaoGrupoTrabalhoEnum;
import br.com.pucrs.tcc.vo.TrabalhoInteresse;

public class ProfessorBD {

	private Session mSession;

	public ProfessorBD(Session session) {
		mSession = session;
	}

	public Professor insert(Professor professor) {
		mSession.save(professor);
		mSession.flush();
		return professor;
	}

	public void update(Professor professor) {
		mSession.update(professor);
		mSession.flush();
	}

	public void delete(Professor professor) {
		mSession.delete(professor);
		mSession.flush();
	}

	public Professor retrieve(Professor professor) {
		Professor professorRetorno = null;

		StringBuilder sql = new StringBuilder();

		sql.append("     SELECT u.*, p.*");
		sql.append("       FROM professores p");
		sql.append(" INNER JOIN usuarios u");
		sql.append("         ON (p.matricula = u.matricula)");
		sql.append("      WHERE p.matricula = ?");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		query.addEntity(Professor.class);
		query.setString(0, professor.getMatricula());

		professorRetorno = (Professor) query.uniqueResult();

		return professorRetorno;
	}

	public ArrayList<Professor> list(Professor professor) {
		ArrayList<Professor> listaRetorno = null;

		StringBuilder sql = new StringBuilder();

		sql.append("     SELECT p.*, u.* ");
		sql.append("       FROM professores p ");
		sql.append(" INNER JOIN usuarios u ");
		sql.append("         ON (p.matricula = u.matricula) ");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		query.addEntity(Professor.class);

		listaRetorno = (ArrayList<Professor>) query.list();

		System.out.println(">>>>>> lista bd: " + listaRetorno.size());

		return listaRetorno;
	}

	public Integer countComGrupo() {
		Integer retorno = 0;

		StringBuilder sql = new StringBuilder();

		sql.append("SELECT p.*");
		sql.append("  FROM professores p");
		sql.append(" WHERE p.num_horas_orientacao > 0");
		sql.append("   AND p.matricula in (SELECT gt.professores_matricula");
		sql.append("                         FROM grupos_trabalho gt");
		sql.append("                        WHERE gt.professores_matricula is not null)");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		retorno = query.list().size();

		return retorno;
	}

	public Integer countSemGrupo() {
		Integer retorno = 0;

		StringBuilder sql = new StringBuilder();

		sql.append("SELECT p.*");
		sql.append("  FROM professores p");
		sql.append(" WHERE p.num_horas_orientacao > 0");
		sql.append("   AND p.matricula not in (SELECT gt.professores_matricula");
		sql.append("                             FROM grupos_trabalho gt");
		sql.append("                            WHERE gt.professores_matricula is not null)");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		retorno = query.list().size();

		return retorno;
	}

	public List<Professor> obtemProfessorComOK(Integer grupoId) {
		List<Professor> professorRetorno = null;

		StringBuilder sql = new StringBuilder();

		sql.append("     SELECT u.*, p.*");
		sql.append("       FROM professores_desejados pd");
		sql.append(" INNER JOIN professores p");
		sql.append("         ON (pd.professores_matricula = p.matricula)");
		sql.append(" INNER JOIN usuarios u");
		sql.append("         ON (p.matricula = u.matricula)");
		sql.append("      WHERE pd.grupos_trabalho_id = ?");
		sql.append("        AND pd.interesse_professor = true");
		sql.append("   ORDER BY pd.ordem_preferencia ");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		query.addEntity(Professor.class);
		query.setInteger(0, grupoId);

		professorRetorno = (List<Professor>) query.list();

		return professorRetorno;
	}

	public Double obterCargaHoraria(Professor professor) {
		Double retorno = 0.0;

		StringBuilder sql = new StringBuilder();

		sql.append("     SELECT count(*) * 0.5 AS carga_horaria ");
		sql.append("       FROM alunos_grupos_trabalho agt ");
		sql.append(" INNER JOIN grupos_trabalho gt ");
		sql.append("         ON (agt.grupos_trabalho_id = gt.id) ");
		sql.append("      WHERE gt.professores_matricula = ? ");
		sql.append("        AND gt.situacao IN (5, 6, 7) ");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		query.setString(0, professor.getMatricula());

		List result = query.list();

		if (result != null) {
			if (result.size() > 0) {
				retorno = Double.parseDouble(result.get(0).toString());
			}
		}

		return retorno;
	}

	public ArrayList<Professor> listaPretendidos(Integer grupoId) {
		ArrayList<Professor> listaRetorno = null;

		StringBuilder sql = new StringBuilder();

		sql.append("     SELECT p.*, u.* ");
		sql.append("       FROM professores_desejados pd ");
		sql.append(" INNER JOIN professores p ");
		sql.append("         ON (pd.professores_matricula = p.matricula) ");
		sql.append(" INNER JOIN usuarios u ");
		sql.append("         ON (p.matricula = u.matricula) ");
		sql.append("      WHERE pd.grupos_trabalho_id = ? ");
		sql.append("   ORDER BY pd.ordem_preferencia ");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		query.addEntity(Professor.class);
		query.setInteger(0, grupoId);

		listaRetorno = (ArrayList<Professor>) query.list();

		return listaRetorno;
	}

	public ArrayList<Professor> listaDisponiveis() {
		ArrayList<Professor> listaRetorno = null;

		StringBuilder sql = new StringBuilder();

		sql.append("     SELECT p.*, u.* ");
		sql.append("       FROM professores p ");
		sql.append(" INNER JOIN usuarios u ");
		sql.append("         ON (p.matricula = u.matricula) ");
		sql.append("      WHERE p.num_horas_orientacao > (    SELECT count(*) * 0.5 ");
		sql.append("     								        FROM alunos_grupos_trabalho agt ");
		sql.append("     							      INNER JOIN grupos_trabalho gt ");
		sql.append("    							     		  ON (agt.grupos_trabalho_id = gt.id) ");
		sql.append("     								       WHERE gt.professores_matricula = p.matricula ");
		sql.append("     								         AND gt.situacao IN (5, 6, 7) )");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		query.addEntity(Professor.class);

		listaRetorno = (ArrayList<Professor>) query.list();

		return listaRetorno;
	}

	public ArrayList<Professor> listaPossiveisOrientadores() {
		ArrayList<Professor> listaRetorno = null;

		StringBuilder sql = new StringBuilder();

		sql.append("     SELECT p.*, u.* ");
		sql.append("       FROM professores p ");
		sql.append(" INNER JOIN usuarios u ");
		sql.append("         ON (p.matricula = u.matricula) ");
		sql.append("      WHERE p.num_horas_orientacao > 0 ");
		sql.append("   ORDER BY u.nome");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		query.addEntity(Professor.class);

		listaRetorno = (ArrayList<Professor>) query.list();

		return listaRetorno;
	}

	public ArrayList<TrabalhoInteresse> listaTrabalhos(String matricula) {
		ArrayList<TrabalhoInteresse> listaRetorno = new ArrayList<TrabalhoInteresse>();

		StringBuilder sql = new StringBuilder();

		sql.append("     SELECT gt.id as grupoId");
		sql.append("          , u.nome as alunos ");
		sql.append("          , c.nome as curso ");
		sql.append("          , pd.professores_matricula as matriculaProfessor ");
		sql.append("          , pd.interesse_professor as interesse ");
		sql.append("          , gt.situacao as situacao");
		sql.append("          , pd.respondido as respondido ");
		sql.append("       FROM professores_desejados pd ");
		sql.append(" INNER JOIN grupos_trabalho gt ");
		sql.append("         ON (gt.id = pd.grupos_trabalho_id) ");
		sql.append(" INNER JOIN alunos_grupos_trabalho ag ");
		sql.append("         ON (gt.id = ag.grupos_trabalho_id) ");
		sql.append(" INNER JOIN cursos c ");
		sql.append("         ON (c.id = gt.cursos_id) ");
		sql.append(" INNER JOIN alunos a ");
		sql.append("         ON (a.matricula = ag.alunos_matricula) ");
		sql.append(" INNER JOIN usuarios u ");
		sql.append("         ON (a.matricula = u.matricula) ");
		sql.append("      WHERE pd.professores_matricula = ? ");
		sql.append("        AND pd.contatado = true ");
		sql.append("   ORDER BY gt.id ");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		query.setString(0, matricula);
		// query.addEntity(TrabalhoInteresse.class);

		// listaRetorno = (ArrayList<TrabalhoInteresse>) query.list();
		List<Object[]> lista = query.list();

		if (lista != null) {
			// System.out.println("Item >>> " + lista.toString());
			TrabalhoInteresse trabalho = null;
			int grupoAnt = 0;
			for (int i = 0; i < lista.size(); i++) {
				Object[] linha = lista.get(i);

				Integer grupoId = Integer.parseInt(linha[0].toString());
				String aluno = linha[1].toString();
				String curso = linha[2].toString();
				String professor = linha[3].toString();
				boolean interesse = Boolean.parseBoolean(linha[4].toString());
				Integer situacao = Integer.parseInt(linha[5].toString());
				boolean respondido = Boolean.parseBoolean(linha[6].toString());

				if (grupoId.equals(grupoAnt)) {
					StringBuilder alunos = new StringBuilder();
					alunos.append(trabalho.getAlunos());
					alunos.append(" | ");
					alunos.append(aluno);

					trabalho.setAlunos(alunos.toString());
				} else {
					if (trabalho != null) {
						listaRetorno.add(trabalho);
					}
					grupoAnt = grupoId;
					trabalho = new TrabalhoInteresse();
					trabalho.setGrupoId(grupoId);
					trabalho.setAlunos(aluno);
					trabalho.setCurso(curso);
					trabalho.setMatriculaProfessor(professor);
					trabalho.setInteresse(interesse);
					trabalho.setSituacao(SituacaoGrupoTrabalhoEnum.getByCodigo(situacao));
					trabalho.setRespondido(respondido);
				}
			}

			if (trabalho != null) {
				listaRetorno.add(trabalho);
			}

		}

		return listaRetorno;
	}

	public TrabalhoInteresse obtemTrabalho(String matricula, Integer grupoId) {
		TrabalhoInteresse retorno = new TrabalhoInteresse();

		StringBuilder sql = new StringBuilder();

		sql.append("     SELECT gt.id as grupoId");
		sql.append("          , u.nome as alunos ");
		sql.append("          , c.nome as curso ");
		sql.append("          , pd.professores_matricula as matriculaProfessor ");
		sql.append("          , pd.interesse_professor as interesse ");
		sql.append("          , gt.situacao as situacao");
		sql.append("          , pd.respondido as respondido ");
		sql.append("       FROM professores_desejados pd ");
		sql.append(" INNER JOIN grupos_trabalho gt ");
		sql.append("         ON (gt.id = pd.grupos_trabalho_id) ");
		sql.append(" INNER JOIN alunos_grupos_trabalho ag ");
		sql.append("         ON (gt.id = ag.grupos_trabalho_id) ");
		sql.append(" INNER JOIN cursos c ");
		sql.append("         ON (c.id = gt.cursos_id) ");
		sql.append(" INNER JOIN alunos a ");
		sql.append("         ON (a.matricula = ag.alunos_matricula) ");
		sql.append(" INNER JOIN usuarios u ");
		sql.append("         ON (a.matricula = u.matricula) ");
		sql.append("      WHERE pd.professores_matricula = ? ");
		sql.append("        AND pd.grupos_trabalho_id = ? ");
		sql.append("   ORDER BY gt.id ");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		query.setString(0, matricula);
		query.setInteger(1, grupoId);

		// listaRetorno = (ArrayList<TrabalhoInteresse>) query.list();
		List<Object[]> lista = query.list();

		if (lista != null) {
			// System.out.println("Item >>> " + lista.toString());
			TrabalhoInteresse trabalho = new TrabalhoInteresse();
			;
			for (int i = 0; i < lista.size(); i++) {
				Object[] linha = lista.get(i);

				Integer idGrupo = Integer.parseInt(linha[0].toString());
				String aluno = linha[1].toString();
				String curso = linha[2].toString();
				String professor = linha[3].toString();
				boolean interesse = Boolean.parseBoolean(linha[4].toString());
				Integer situacao = Integer.parseInt(linha[5].toString());
				boolean respondido = Boolean.parseBoolean(linha[6].toString());

				trabalho.setGrupoId(idGrupo);
				trabalho.setAlunos(aluno);
				trabalho.setCurso(curso);
				trabalho.setMatriculaProfessor(professor);
				trabalho.setInteresse(interesse);
				trabalho.setSituacao(SituacaoGrupoTrabalhoEnum.getByCodigo(situacao));
				trabalho.setRespondido(respondido);

				StringBuilder alunos = new StringBuilder();
				alunos.append(trabalho.getAlunos());
				alunos.append(" | ");
				alunos.append(aluno);
				trabalho.setAlunos(alunos.toString());
			}

			return trabalho;
		}

		return null;
	}

	public boolean respondeInteresse(ProfessorPretendido pd) {
		boolean retorno = false;

		StringBuilder sql = new StringBuilder();
		sql.append("UPDATE professores_desejados ");
		sql.append("   SET interesse_professor = ? ");
		sql.append("     , respondido = true ");
		sql.append(" WHERE grupos_trabalho_id = ? ");
		sql.append("   AND professores_matricula = ? ");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		query.setBoolean(0, pd.getInteresseProfessor());
		query.setInteger(1, pd.getGrupo().getId());
		query.setString(2, pd.getProfessor().getMatricula());

		int result = query.executeUpdate();

		retorno = result == 1;

		return retorno;
	}

	public ArrayList<Professor> listaPorArea(AreaInteresse area, Integer ordemPreferencia) {
		ArrayList<Professor> listaRetorno = null;

		StringBuilder sql = new StringBuilder();

		sql.append("     SELECT p.*, u.* ");
		sql.append("       FROM professores p ");
		sql.append(" INNER JOIN usuarios u ");
		sql.append("         ON (p.matricula = u.matricula) ");
		sql.append(" INNER JOIN professores_areas_interesse pa ");
		sql.append("         ON (p.matricula = pa.professores_matricula) ");
		sql.append("      WHERE pa.areas_interesse_id = ? ");
		sql.append("   ORDER BY pa.ordem_preferencia ");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		query.addEntity(Professor.class);
		query.setInteger(0, area.getId());
		// query.setInteger(1, ordemPreferencia);

		listaRetorno = (ArrayList<Professor>) query.list();

		return listaRetorno;
	}

	public ArrayList<Professor> listaAvaliadores(GrupoTrabalho grupo) {
		ArrayList<Professor> listaRetorno = null;

		StringBuilder sql = new StringBuilder();

		sql.append("     SELECT p.*, u.* ");
		sql.append("       FROM professores p ");
		sql.append(" INNER JOIN usuarios u ");
		sql.append("         ON (p.matricula = u.matricula) ");
		sql.append(" INNER JOIN avaliadores a ");
		sql.append("         ON (p.matricula = a.professores_matricula) ");
		sql.append("      WHERE a.grupos_trabalho_id = ? ");

		SQLQuery query = mSession.createSQLQuery(sql.toString());
		query.addEntity(Professor.class);
		query.setInteger(0, grupo.getId());

		listaRetorno = (ArrayList<Professor>) query.list();

		return listaRetorno;
	}
}
